home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / c2man-2.0pl33.lha / c2man-2.0 / vms / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-24  |  4.5 KB  |  189 lines

  1. /* Implement unix popen and pclose in vms by using mailboxes
  2.    and lib$spawn.
  3.    17-APR-91 -GJC@MITECH.COM version 1.0
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <descrip.h>
  8. #include <ssdef.h>
  9. #include <string.h>
  10.  
  11. FILE *popen();
  12. int pclose();
  13.  
  14. globalvalue CLI$M_NOWAIT;
  15.  
  16. void p_describe(); /* a non-unix function */
  17.  
  18. static struct dsc$descriptor *set_dsc_cst();
  19. static int create_mbx();
  20.  
  21. #define mailbox_size (512)
  22. #define mailbox_byte_quota (3*mailbox_size)
  23. #define mailbox_protection_mask (0x0000F000)
  24.  
  25. struct popen_cell
  26. {FILE *fp;
  27.  char *mbx_name;
  28.  short mbx_chan;
  29.  long pid;
  30.  long completed;
  31.  long comp_status;
  32.  struct popen_cell *next;
  33.  struct popen_cell *prev;};
  34.  
  35. static struct popen_cell *popen_list = NULL;
  36.  
  37. static struct popen_cell *find_popen_cell(fp)
  38.      FILE *fp;
  39. {struct popen_cell *l;
  40.  for(l=popen_list;l != NULL; l = l->next)
  41.    if (l->fp == fp) return(l);
  42.  return(NULL);}
  43.  
  44. void p_describe(fp)
  45.      FILE *fp;
  46. {struct popen_cell *cell;
  47.  if (!(cell = find_popen_cell(fp)))
  48.    {printf("File pointer is not from popen, or it has been closed\n");
  49.     return;}
  50.  printf("FILE *fp                = %08X\n",cell->fp);
  51.  printf("char *mbx_name          = %s\n",cell->mbx_name);
  52.  printf("short mbx_chan          = %d\n",cell->mbx_chan);
  53.  printf("long pid                = %08X\n",cell->pid);
  54.  printf("long completed          = %d\n",cell->completed);
  55.  printf("long comp_status        = %d\n",cell->comp_status);
  56.  printf("struct popen_cell *next = %08X\n",cell->next);
  57.  printf("struct popen_cell *prev = %08X\n",cell->prev);}
  58.  
  59. static void proc_exit_ast(cell)
  60.      struct popen_cell *cell;
  61. {cell->completed = 1;}
  62.  
  63. static void pclose_cleanup(cell)
  64.      struct popen_cell *cell;
  65. {sys$dassgn(cell->mbx_chan);
  66.  free(cell->mbx_name);
  67.  if (!cell->completed)
  68.    sys$delprc(&cell->pid,0);
  69.  memset(cell,0,sizeof(struct popen_cell));
  70.  free(cell);}
  71.  
  72. static void pclose_delq(cell)
  73.      struct popen_cell *cell;
  74. {if (cell->prev)
  75.    {cell->prev->next = cell->next;
  76.     if (cell->next)
  77.       cell->next->prev = cell->prev;}
  78.  else
  79.    {popen_list = cell->next;
  80.     if (cell->next)
  81.       cell->next->prev = NULL;}}
  82.  
  83. static void popen_push(cell)
  84.      struct popen_cell *cell;
  85. {if (popen_list)
  86.    popen_list->prev = cell;
  87.  cell->prev = NULL;
  88.  cell->next = popen_list;
  89.  popen_list = cell;}
  90.  
  91. int pclose(fp)
  92.      FILE *fp;
  93. {int i;
  94.  struct popen_cell *cell;
  95.  i = fclose(fp);
  96.  if (cell = find_popen_cell(fp))
  97.    {pclose_delq(cell);
  98.     pclose_cleanup(cell);}
  99.  return(i);}
  100.  
  101. FILE *popen(command,mode)
  102.      char *command,*mode;
  103. {char *temp;
  104.  struct popen_cell *cell;
  105.  int readp,n,mask,ret;
  106.  char *name,*prompt,*in,*out;
  107.  struct dsc$descriptor comm_d,in_d,out_d,name_d,prompt_d;
  108.  
  109.  if (strcmp(mode,"r") == 0)
  110.    readp = 1;
  111.  else if (strcmp(mode,"w") == 0)
  112.    readp = 0;
  113.  else
  114.    return(NULL);
  115.  
  116.  temp = mktemp("POPEN_MB_XXXXXXXXXX");
  117.  n = strlen(temp);
  118.   cell =  (struct popen_cell *) malloc(sizeof(struct popen_cell));
  119.  cell->mbx_name = (char *) malloc(n+1);
  120.  strcpy(cell->mbx_name,temp);
  121.  if ((cell->mbx_chan = create_mbx(cell->mbx_name)) < 0)
  122.    {cell->completed = 1;
  123.     pclose_cleanup(cell);
  124.     return(NULL);}
  125.  
  126.  if (readp)
  127.    {in = "NL:";
  128.     out = cell->mbx_name;}
  129.  else
  130.    {in = cell->mbx_name;
  131.     out = "NL:";}
  132.  
  133.  name = 0;
  134.  prompt = 0;
  135.  mask = CLI$M_NOWAIT;
  136.  
  137.  cell->completed = 0;
  138.  
  139.  ret = lib$spawn((command) ? set_dsc_cst(&comm_d,command) : 0,
  140.                  (in) ? set_dsc_cst(&in_d,in) : 0,
  141.                  (out) ? set_dsc_cst(&out_d,out) : 0,
  142.                  &mask,
  143.                  (name)  ? set_dsc_cst(&name_d,name) : 0,
  144.                  &cell->pid,
  145.                  &cell->comp_status,
  146.                  0, /* event flag */
  147.          proc_exit_ast,
  148.          cell,
  149.                  (prompt) ? set_dsc_cst(&prompt_d,prompt) : 0,
  150.                  0 /* cli */
  151.                  );
  152.  
  153.  if (ret != SS$_NORMAL)
  154.    {cell->completed = 1;
  155.     pclose_cleanup(cell);
  156.     return(NULL);}
  157.  
  158.  if (!(cell->fp = fopen(cell->mbx_name,mode)))
  159.    {pclose_cleanup(cell);
  160.     return(NULL);}
  161.  
  162.  popen_push(cell);
  163.  
  164.  return(cell->fp);}
  165.  
  166. static struct dsc$descriptor *set_dsc_cst(x,buff)
  167.      struct dsc$descriptor *x;
  168.      char *buff;
  169. {(*x).dsc$w_length = strlen(buff);
  170.  (*x).dsc$a_pointer = buff;
  171.  (*x).dsc$b_class = DSC$K_CLASS_S;
  172.  (*x).dsc$b_dtype = DSC$K_DTYPE_T;
  173.  return(x);}
  174.  
  175. static int create_mbx(name)
  176.   char *name;
  177. {short chan;
  178.  int prmflg,maxmsg,bufquo,promsk,acmode,iflag,retval;
  179.  struct dsc$descriptor lognam;
  180.  prmflg = 0;
  181.  maxmsg = mailbox_size;
  182.  bufquo = mailbox_byte_quota;
  183.  promsk = mailbox_protection_mask;
  184.  acmode = 0;
  185.  set_dsc_cst(&lognam,name);
  186.  retval = sys$crembx(prmflg,&chan,maxmsg,bufquo,promsk,acmode,&lognam);
  187.  if (retval != SS$_NORMAL) return(-1);
  188.  return(chan);}
  189.